package net.guerlab.sdk.dingtalk.client.impl;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.guerlab.sdk.dingtalk.DingTalkConstants;
import net.guerlab.sdk.dingtalk.DingTalkException;
import net.guerlab.sdk.dingtalk.client.AbstractDingTalkClient;
import net.guerlab.sdk.dingtalk.request.AbstractRequest;
import net.guerlab.sdk.dingtalk.response.AbstractResponse;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

/**
 * 默认钉钉请求客户端
 *
 * @author guer
 */
@Slf4j
@Setter
@Getter
public class DefaultDingTalkClient extends AbstractDingTalkClient {

    private static final String HEADER_NAME_CONTENT_TYPE = "Content-Type";

    /**
     * http请求客户端
     */
    private HttpClient client;

    /**
     * 构造钉钉请求客户端
     *
     * @param client
     *         http请求客户端
     */
    public DefaultDingTalkClient(HttpClient client) {
        this.client = client;
    }

    @Override
    protected <RS extends AbstractResponse> RS executeWithHttpRequest(AbstractRequest<RS> request, String uri) {
        HttpRequest.Builder builder = HttpRequest.newBuilder();
        builder.uri(URI.create(uri));

        setContent(request, builder);

        try {
            HttpRequest httpRequest = builder.build();
            String responseBody = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body();

            log.debug("request uri: [{}]", httpRequest.uri());
            log.debug("response body: [{}]", responseBody);

            RS response = objectMapper.readValue(responseBody, request.getResponseClass());

            if (response.getErrcode() != 0) {
                throw new DingTalkException(response.getErrmsg(), response.getErrcode());
            }

            return response;
        } catch (Exception e) {
            throw new DingTalkException(e.getLocalizedMessage(), e);
        }
    }

    private <RS extends AbstractResponse> void setContent(AbstractRequest<RS> request, HttpRequest.Builder builder) {
        String content = request.getRequestContent();
        HttpRequest.BodyPublisher bodyPublisher;
        if (content != null) {
            bodyPublisher = HttpRequest.BodyPublishers.ofString(content);
        } else {
            bodyPublisher = HttpRequest.BodyPublishers.noBody();
        }

        if (DingTalkConstants.METHOD_GET.equals(request.getMethod())) {
            builder.GET();
        } else if (DingTalkConstants.METHOD_POST.equals(request.getMethod())) {
            builder.header(HEADER_NAME_CONTENT_TYPE, DingTalkConstants.CONTENT_TYPE_JSON).POST(bodyPublisher);
        } else if (DingTalkConstants.METHOD_PUT.equals(request.getMethod())) {
            builder.header(HEADER_NAME_CONTENT_TYPE, DingTalkConstants.CONTENT_TYPE_JSON).PUT(bodyPublisher);
        } else if (DingTalkConstants.METHOD_DELETE.equals(request.getMethod())) {
            builder.DELETE();
        }
    }
}
